package com.ddwl.wallet.service;

import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.exception.CommonException;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.feign.api.GoodsApi;
import com.ddwl.common.feign.api.ShopApi;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.wallet.IssueCouponBo;
import com.ddwl.schema.bo.wallet.UserCouponBo;
import com.ddwl.schema.vo.goods.ItemVo;
import com.ddwl.schema.vo.wallet.CouponVo;
import com.ddwl.schema.vo.wallet.UserCouponVo;
import com.ddwl.wallet.dao.model.Coupon;
import com.ddwl.wallet.dao.model.UserCoupon;
import com.ddwl.wallet.repository.CouponRepository;
import com.ddwl.wallet.repository.UserCouponRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author hemiaojun
 * @Date 2021/9/7 18:00
 */
@Service
@RequiredArgsConstructor
public class UserCouponService {

    private final UserCouponRepository userCouponRepository;
    private final CouponRepository couponRepository;
    private final GoodsApi goodsApi;
    private final ShopApi shopApi;

    /**
     * 用户拥有的优惠券
     *
     * @param pageBo
     * @return
     */
    public List<UserCouponVo> user(PageBo pageBo) {
        List<UserCoupon> userCoupons = userCouponRepository.findByUserId(pageBo);
        // FIXME 这时暂时没作优化，每张券都查询了一次门店或商品
        return userCoupons.stream().map(userCoupon -> {
            UserCouponVo vo = BeanConverUtils.convertBean(userCoupon, UserCouponVo.class);
            Coupon coupon = userCoupon.getCoupon();
            CouponVo couponVo = BeanConverUtils.convertBean(coupon, CouponVo.class);
            if (!CollectionUtils.isEmpty(coupon.getShopIds())) {
                couponVo.setShops(shopApi.getShopListByIds(userCoupon.getCoupon().getShopIds()).getResult());
            }
            if (StringUtils.hasText(coupon.getItemId())) {
                couponVo.setItem(goodsApi.getItemInfo(coupon.getItemId()).getResult());
            }
            vo.setCoupon(couponVo);
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 发放优惠券
     *
     * @param list
     */
    public void issueCoupon(List<IssueCouponBo> list) {
        list.forEach(bo -> {
            for (int i = 0; i < bo.getQty(); i++) {
                UserCoupon uc = new UserCoupon();
                uc.setCouponNo(UUIDGenerator.getShortUUID());
                uc.setCoupon(new Coupon(bo.getCouponId()));
                uc.setUserId(bo.getUserId());
                uc.setStatus(BaseEnum.UseEnum.UN_USE.getCode());
                uc.setGmtCreated(Instant.now());
                userCouponRepository.save(uc);
            }
        });
    }

    /**
     * 领取优惠券
     *
     * @param bo
     */
    public void takeCoupon(UserCouponBo bo) {
        Coupon coupon = couponRepository.findById(bo.getCouponId()).orElse(null);
        ParamException.isNull(coupon);
        if (coupon.getSingleMax() != null) {
            Long count = userCouponRepository.countByUserIdAndCouponId(bo.getUserId(), bo.getCouponId());
            if (count >= coupon.getSingleMax()) {
                throw new CommonException("您已领取过券，不要太贪心哦~~");
            }
        }
        UserCoupon uc = new UserCoupon();
        uc.setCouponNo(UUIDGenerator.getShortUUID());
        uc.setCoupon(new Coupon(bo.getCouponId()));
        uc.setUserId(bo.getUserId());
        uc.setStatus(BaseEnum.UseEnum.UN_USE.getCode());
        uc.setGmtCreated(Instant.now());
        userCouponRepository.save(uc);
    }

    /**
     * 核销
     *
     * @param
     */
    public void checkCoupon(String userCouponId,Boolean use) {
        UserCoupon userCoupon = userCouponRepository.findById(userCouponId).orElse(null);
        ParamException.isNull(userCoupon);
        if (userCoupon.getStatus().equals(BaseEnum.UseEnum.USED.getCode())) {
            throw new CommonException("优惠券已被使用");
        }
        if (userCoupon.getStatus().equals(BaseEnum.UseEnum.EXPIRED.getCode())) {
            throw new CommonException("优惠券已过期");
        }
        if(use){
            userCoupon.setStatus(BaseEnum.UseEnum.USED.getCode());
            userCoupon.setGmtModified(Instant.now());
            userCouponRepository.save(userCoupon);
        }
    }

    /**
     * 商品可使用优惠券
     *
     * @param userId
     * @param itemIds
     * @return
     */
    public List<UserCouponVo> item(String userId, List<String> itemIds) {
        List<ItemVo> items = goodsApi.queryItems(itemIds).getResult();
        BigDecimal amount = items.stream().map(ItemVo::getRetailPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        List<Coupon> reductionCoupons = couponRepository.findByAmount(amount);
        List<Coupon> itemCoupons = couponRepository.findByItem(itemIds);
        List<Coupon> voucherCoupons = couponRepository.findByVoucher();
        if (CollectionUtils.isEmpty(itemCoupons) && CollectionUtils.isEmpty(voucherCoupons)) {
            return new ArrayList<>();
        }
        voucherCoupons.addAll(reductionCoupons);
        voucherCoupons.addAll(itemCoupons);
        List<UserCoupon> userCoupons = userCouponRepository.findByUserIdAndCouponId(userId, voucherCoupons.stream().map(Coupon::getId).collect(Collectors.toList()));
        return userCoupons.stream().map(userCoupon -> {
            UserCouponVo vo = BeanConverUtils.convertBean(userCoupon, UserCouponVo.class);
            vo.setCoupon(BeanConverUtils.convertBean(userCoupon.getCoupon(), CouponVo.class));
            return vo;
        }).collect(Collectors.toList());
    }

    public List<UserCouponVo> info(List<String> userCouponIds) {
        List<UserCoupon> userCoupons = userCouponRepository.findByIds(userCouponIds);
        return userCoupons.stream().map(userCoupon -> {
            UserCouponVo vo = BeanConverUtils.convertBean(userCoupon, UserCouponVo.class);
            vo.setCoupon(BeanConverUtils.convertBean(userCoupon.getCoupon(), CouponVo.class));
            return vo;
        }).collect(Collectors.toList());
    }

    public void expireCoupon() {
        userCouponRepository.updateExpire();
    }
}
